const config_module = require('./config');
const Redis = require('redis');


// 创建 Redis 客户端（适配 v4+ 语法）
const redisCli = Redis.createClient({
  socket: {
    host: config_module.redis_host,
    port: config_module.redis_port,
    reconnectStrategy: (retries) => Math.min(retries * 500, 5000) // 指数退避重连策略
  },
  password: config_module.redis_pass,
  disableOfflineQueue: true,      // 更安全的离线队列设置
  pingInterval: 30000            // 每30秒自动发送心跳
});

// 连接状态标记
let isConnected = false;

// 显式连接并处理初始连接
async function initializeRedis() {
  try {
    await redisCli.connect();
    console.log('Redis 已连接');
    isConnected = true;
  } catch (err) {
    console.error('初始连接失败:', err);
    process.exit(1); // 关键服务依赖失败时退出
  }
}

// 事件监听
redisCli.on('ready', () => {
  console.log('Redis 已就绪');
  isConnected = true;
});

redisCli.on('error', (err) => {
  console.error('Redis 错误:', err);
  isConnected = false;
});

redisCli.on('end', () => {
  console.log('Redis 连接断开');
  isConnected = false;
});

// 安全执行 Redis 命令的包装器
async function safeRedisCommand(fn) {
  if (!isConnected) {
    throw new Error('Redis 未连接');
  }
  try {
    return await fn();
  } catch (err) {
    if (err.code === 'NR_CLOSED') { // 客户端关闭错误代码
      await handleReconnect();
      return await fn();
    }
    throw err;
  }
}

// 重连处理器
async function handleReconnect() {
  try {
    console.log('尝试重新连接...');
    await redisCli.disconnect();
    await redisCli.connect();
    isConnected = true;
  } catch (err) {
    console.error('重连失败:', err);
  }
}

/**
 * 设置key和value，并过期时间
 * @param {*} key 
 * @param {*} value 
 * @param {*} exptime 
 * @returns 
 */
async function SetNxRedisExpire(key, value, exptime) {
  return safeRedisCommand(async () => {
    if (typeof exptime !== "number" || exptime <= 0) {
      throw new Error(`Invalid expiration time: ${exptime}`);
    }
    // NX（Not eXists）仅在键 不存在 时执行设置操作。
    // EX（EXpire Time） 过期时间，单位秒
    await redisCli.set(key, value, { NX: true, EX: exptime });
    return true;
  });
}

/**
 * 根据key获取value
 * @param {*} key 
 */
async function GetRedis(key) {
  return safeRedisCommand(async () => {
    const result = await redisCli.get(key);
    if (result === null) {
      // 防止缓存穿透
      await redisCli.setEx(key, 60, "NULL");
      return null;
    }
    return result;
  });
}

/**
 * 根据key查询redis中是否存在key
 * @param {*} key 
 */
async function QueryRedis(key) {
  return safeRedisCommand(async () => {
    return await redisCli.exists(key);
  });
}

/**
 * 根据key删除value
 * @param {*} key 
 */
async function DeleteRedis(key) {
  return safeRedisCommand(async () => {
    return await redisCli.del(key);
  });
}







// 优雅关闭
process.on('SIGINT', async () => {
  console.log('\n正在关闭 Redis 连接...');
  try {
    await redisCli.quit();
    console.log('Redis 连接已安全关闭');
  } catch (err) {
    console.error('关闭连接时出错:', err);
  } finally {
    process.exit(0);
  }
});

// 初始化 Redis
initializeRedis();

module.exports = {
  redisCli,
  SetNxRedisExpire,
  GetRedis,
  QueryRedis,
  DeleteRedis,
  initializeRedis
};